﻿/*-------------------------------------------------------------------------
* 命名空间: XrayDirection.Common/ImageCapture
* 类       名: ImageCapture
* 功      能:  TD
* 时      间:  2024/1/26 11:42:27
* 版      本:  V1.0
* 作      者:  Fioman
* 格      言:  Talk is cheap,show me the code ^_^
*-------------------------------------------------------------------------*/
using OpenCvSharp;
using SiliconSelect.Common;
using System;
using System.Diagnostics;
using System.IO;
using XrayDirection.Extensions;
using XrayDirection.HelperManager;

namespace XrayDirection.Common
{
    public class ImageCapture
    {
        // 每次读取图像刷新几次图像
        public int flushCount = 12;

        private static ImageCapture _instance;
        private static readonly object _lock = new object();

        public bool isOnline01;
        public bool isOnline02;
        public Mat? image01;
        public Mat? image02;
        public Mat imageFlush01;
        public Mat imageFlush02;
        public VideoCapture? capture01;
        public VideoCapture? capture02;
        private ImageCapture()
        {
            isOnline01 = false;
            isOnline02 = false;
            image01 = null;
            image02 = null;
            imageFlush01 = new Mat();
            imageFlush02 = new Mat();
            // 默认创建对象的时候就打开摄像头
            DataResult openRes01 = OpenCapture01();
            DataResult openRes02 = OpenCapture02();
            if (!openRes01.State || !openRes02.State)
            {
                ImageErrorMsg = openRes01.Message + " " + openRes02.Message;
            }
        }

        public string? ImageErrorMsg { get; set; }
        public static ImageCapture Instance
        {
            get
            {
                if (_instance == null)
                {
                    lock (_lock)
                    {
                        if (_instance == null)
                        {
                            _instance = new ImageCapture();
                        }
                    }
                }
                return _instance;
            }
        }

        // 打开摄像头01
        public DataResult OpenCapture01()
        {
            DataResult result = new DataResult();
            if (capture01 != null)
            {
                capture01.Release();
                capture01 = null;
            }
            capture01 = new VideoCapture(0, VideoCaptureAPIs.DSHOW);
            if (capture01.IsOpened())
            {
                // 打开成功
                result.State = true;
                result.Message = "Xray01打开成功!";
            }
            else
            {
                result.Message = "Xray01打开失败,请检查摄像头USB连接线是否松动";
            }
            return result;
        }

        // 打开摄像头02
        public DataResult OpenCapture02()
        {
            DataResult result = new DataResult();
            if (capture02 != null)
            {
                capture02.Release();
                capture02 = null;
            }
            capture02 = new VideoCapture(1, VideoCaptureAPIs.DSHOW);
            if (capture02.IsOpened())
            {
                // 打开成功
                result.State = true;
                result.Message = "Xray02打开成功!";
            }
            else
            {
                result.Message = "Xray02打开失败,请检查摄像头USB连接线是否松动";
            }
            return result;
        }

        // 检查摄像头是否在线,如果在线就不停地读取5帧的图像,返回值1,表示1个在线,2表示两个在线,0表示都不在线
        public DataResult<int> CheckIsOnlineAndFlush()
        {
            //OpenCapture01();
            //OpenCapture02();
            DataResult<int> result = new DataResult<int>();
            int resultData = 0;
            if (capture01 != null && capture01.IsOpened())
            {
                for (int i = 0; i < flushCount; i++)
                {
                    capture01.Read(imageFlush01);
                }
                resultData = 1;
            }

            if (capture02 != null && capture02.IsOpened())
            {
                for (int i = 0; i < flushCount; i++)
                {
                    capture02.Read(imageFlush02);
                }
                if (resultData == 1)
                {
                    resultData = 2;
                    result.State = true;
                }
                else
                {
                    resultData = 1;
                }
            }
            result.Data = resultData;
            //capture01?.Release();
            //capture02?.Release();
            //capture01 = null;
            //capture02 = null;
            return result;
        }

        // 获取图片,获取图片,如果获取失败
        public DataResult<Mat> GetImage01()
        {
            Stopwatch stopwatch = Stopwatch.StartNew();
            stopwatch.Start();
            //OpenCapture01();
            DataResult<Mat> result = new DataResult<Mat>();
            try
            {
                image01 = null;
                if (capture01 != null && capture01.IsOpened())
                {
                    for (int i = 0; i < flushCount; i++)
                    {
                        capture01.Read(imageFlush01);
                    }
                    image01 = imageFlush01;
                    bool res = capture01.Read(image01);
                    if (res)
                    {
                        var newFrame = new Mat(image01, new Rect(32, 0, image01.Width - 32, image01.Height));
                        var flipFrame = new Mat();
                        Cv2.Flip(newFrame, flipFrame, FlipMode.Y);
                        Mat flipFrameGray = new Mat();
                        Cv2.CvtColor(flipFrame, flipFrameGray, ColorConversionCodes.BGR2GRAY);
                        result.Data = flipFrameGray;
                        result.State = true;
                    }
                    else
                    {
                        image01 = null;
                        result.Message = "Xray01图像读取失败,请排查图像读取失败原因!";
                    }
                }
                else
                {
                    result.Message = "Xray01摄像头打开失败,检查摄像头USB接线是否良好!";
                }
            }
            catch (Exception ex)
            {
                result.Message = ex.GetFullException();
            }
            //capture01?.Release();
            //capture01 = null;
            stopwatch.Stop();
            LogHelper.WriteLog($"Xray01取图耗时:{stopwatch.Elapsed.TotalMilliseconds}");
            return result;
        }

        public DataResult<Mat> GetImage02()
        {
            Stopwatch stopwatch = Stopwatch.StartNew();
            stopwatch.Start();
            //OpenCapture02();
            DataResult<Mat> result = new DataResult<Mat>();
            try
            {
                image02 = null;
                if (capture02 != null && capture02.IsOpened())
                {
                    for (int i = 0; i < flushCount; i++)
                    {
                        capture02!.Read(imageFlush02);
                    }
                    image02 = imageFlush02;
                    bool res = capture02!.Read(image02);
                    if (res)
                    {
                        var newFrame = new Mat(image02, new Rect(32, 0, image02.Width - 32, image02.Height));
                        var flipFrame = new Mat();
                        Cv2.Flip(newFrame, flipFrame, FlipMode.Y);
                        Mat flipFrameGray = new Mat();
                        Cv2.CvtColor(flipFrame, flipFrameGray, ColorConversionCodes.BGR2GRAY);
                        result.Data = flipFrameGray;
                        result.State = true;
                    }
                    else
                    {
                        image02 = null;
                        result.Message = "Xray02图像读取失败,请排查图像读取失败原因!";
                    }
                }
                else
                {
                    result.Message = "Xray02摄像头打开失败,检查摄像头USB接线是否良好!";
                }
            }
            catch (Exception ex)
            {
                result.Message = ex.GetFullException();
            }
            //capture02?.Release();
            //capture02 = null;
            stopwatch.Stop();
            LogHelper.WriteLog($"Xray02取图耗时:{stopwatch.Elapsed.TotalMilliseconds}");
            return result;
        }


        /// <summary>
        /// 根据文件名称去获取图像的编号,用来判断是属于xray01还是xray02.
        /// 如果返回01表示的是xray01,如果返回02,表示的是xray02
        /// </summary>
        /// <param name="fileName"></param>
        /// <returns></returns>
        public static string GetImageNumber(string fileName)
        {
            if (string.IsNullOrEmpty(fileName))
            {
                return "文件名无效";
            }
            /*
             * 后面这个参数StringSplitOptions.None: 表示Split方法在遇到连续的"--"分隔符的时候将会包含空字符串到结果数组中.
             * 比如: 2023--11----01 的结果就是 2023 11 "" 01
             * 如果你不想要空字符串,你可以使用这个表示 StringSplitOptions.RemoveEmptyEntries
             * 结果就是 2023 11 01
             */
            // 去除掉文件扩展名
            fileName = Path.GetFileNameWithoutExtension(fileName);

            string[] parts = fileName.Split(new string[] { "--" }, StringSplitOptions.None);
            if (parts.Length == 0)
            {
                return "文件名无效,必须是包含--,并且以01或者02结尾";
            }
            else
            {
                string number = parts[^1];
                if (number.Contains("01") && number.Contains("02"))
                {
                    return "文件名无效,必须是包含--,并且以01或者02结尾";
                }
                return number;
            }
        }


        public static void SaveEdgeImageOk(int imageIndex, Mat image)
        {
            string saveFileName = $"{imageIndex}--{DateTimeHelper.GetTimeNowForKeepImage()}.bmp";
            string saveFilePath = Path.Combine(ConstantManager.FindEdgeDirOk, saveFileName);
            Cv2.ImWrite(saveFilePath, image);
        }

        public static void SaveEdgeImageFail(int imageIndex, Mat image)
        {
            string saveFileName = $"{imageIndex}--{DateTimeHelper.GetTimeNowForKeepImage()}.bmp";
            string saveFilePath = Path.Combine(ConstantManager.FindEdgeDirFail, saveFileName);
            Cv2.ImWrite(saveFilePath, image);
        }

        public static void SaveEdgeImageRes(int imageIndex, Mat image)
        {
            string saveFileName = $"{imageIndex}--{DateTimeHelper.GetTimeNowForKeepImage()}.bmp";
            string saveFilePath = Path.Combine(ConstantManager.FindEdgeDirRes, saveFileName);
            Cv2.ImWrite(saveFilePath, image);
        }


        public static void SaveTargetImageOk(int imageIndex, Mat image, string xrayName)
        {
            string saveFileName = $"{imageIndex}--{DateTimeHelper.GetTimeNowForKeepImage()}--{xrayName}.bmp";
            string saveFilePath = Path.Combine(ConstantManager.FindTargetDirOk, saveFileName);
            Cv2.ImWrite(saveFilePath, image);
        }

        public static void SaveTargetImageFail(int imageIndex, Mat image, string xrayName)
        {
            string saveFileName = $"{imageIndex}--{DateTimeHelper.GetTimeNowForKeepImage()}--{xrayName}.bmp";
            string saveFilePath = Path.Combine(ConstantManager.FindTargetDirFail, saveFileName);
            Cv2.ImWrite(saveFilePath, image);
        }

        public static void SaveTargetImageRes(int imageIndex, Mat image, string xrayName)
        {
            string saveFileName = $"{imageIndex}--{DateTimeHelper.GetTimeNowForKeepImage()}--{xrayName}.bmp";
            string saveFilePath = Path.Combine(ConstantManager.FindTargetDirRes, saveFileName);
            Cv2.ImWrite(saveFilePath, image);
        }
    }
}
